/*
 * NetworkManager.hpp
 *
 *  Created on: Dec 11, 2014
 *      Author: toti
 */

#ifndef IBRCNETWORKMANAGER_HPP_
#define IBRCNETWORKMANAGER_HPP_

#include <list>

#include <Connectivity/ConnectionManager.hpp>
#include <Network/LocalNode.hpp>
#include <Network/LocalClient.hpp>
#include <Network/LocalServer.hpp>
#include <Network/NetworkChannel.hpp>
#include <Network/NetworkClient.hpp>
#include <Network/NetworkServer.hpp>
#include <Network/NetworkRequests/NetworkRequest.hpp>
#include <Network/NetworkRequests/CreateChannelNetworkRequest.hpp>
#include <Network/NetworkRequests/CreateNickNetworkRequest.hpp>
#include <Network/NetworkRequests/RemoveChannelNetworkRequest.hpp>
#include <Network/MessagePackages/MessagePackage.hpp>
#include <Network/MessagePackages/ClientMessagePackage.hpp>
#include <Network/MessagePackages/ServerMessagePackage.hpp>

class IBRCNetworkManager{

public:

	enum IBRCNetworkManagerState{
		STATE_RUNNING,
		STATE_QUIT
	};

private:

	IBRCNetworkManagerState ibrcNetworkManagerState;

	ConnectionManager *connectionManager;

	NetworkServer *networkServer;
	NetworkClient *networkClient;

	std::list<NetworkServer*> *networkServerList;
	std::list<NetworkClient*> *networkClientList;
	std::list<NetworkChannel*> *networkChannelList;

	/*
	 * Server functions
	 */
	void processServerMessagePackage(ServerMessagePackage *serverMessagePackage);

	void processServerRegistration(ServerMessagePackage *package);
	void processServerUnregistration(ServerMessagePackage *package);
	void processServerReconnect(ServerMessagePackage *package);
	void processServerUpdateClientList(ServerMessagePackage *package);
	void processServerUpdateChannelList(ServerMessagePackage *package);
	void processServerUpdateRequestServerList(ServerMessagePackage *package);
	void processServerUpdateRequestClientList(ServerMessagePackage *package);
	void processServerUpdateRequestChannelList(ServerMessagePackage *package);
	void processServerResponse(ServerMessagePackage *package);
	void processServerChannelMessage(ServerMessagePackage *package);
	void processServerChannelPrivateMessage(ServerMessagePackage *package);

	void processServerRequestSettopic(ServerMessagePackage *package);
	void processServerRequestJoin(ServerMessagePackage *package);
	void processServerRequestLeave(ServerMessagePackage *package);
	void processServerRequestNick(ServerMessagePackage *package);
	void processServerRequestQuit(ServerMessagePackage *package);


	/*
	 * Client functions
	 */
	void processClientMessagePackage(ClientMessagePackage *clientMessagePackage);

	void processClientRegistrationMessage(ClientMessagePackage *clientMessagePackage);
	void processClientChannelMessage(ClientMessagePackage *clientMessagePackage);
	void processClientGettopicMessage(ClientMessagePackage *clientMessagePackage);
	void processClientJoinMessage(ClientMessagePackage *clientMessagePackage);
	void processClientLeaveMessage(ClientMessagePackage *clientMessagePackage);
	void processClientListMessage(ClientMessagePackage *clientMessagePackage);
	void processClientNickMessage(ClientMessagePackage *clientMessagePackage);
	void processClientPrivateMessage(ClientMessagePackage *clientMessagePackage);
	void processClientQuitMessage(ClientMessagePackage *clientMessagePackage);
	void processClientSettopicMessage(ClientMessagePackage *clientMessagePackage);


	/*
	 * Misc
	 */
	void performForwardBroadcast(ServerMessagePackage *serverMessagePackage);
	void performCompleteBroadcast(ServerMessagePackage *serverMessagePackage);


	/*
	 * List finders
	 */
	NetworkRequest 				*findNetworkRequestById(std::string& id);
	RemoveChannelNetworkRequest *findRemoveChannelNetworkRequestByName(std::string& name);
	NetworkClient 				*findNetworkClientByName(std::string& name);
	NetworkClient				*findNetworkClientByServer(NetworkServer *networkServer);
	void 						*findNetworkClientsByChannel(std::list<NetworkClient*> *clientList, NetworkChannel *networkChannel);
	NetworkChannel 				*findNetworkChannelByName(std::string& name);
	NetworkChannel				*findNetworkChannelByOwner(NetworkClient *networkClient);
	void 						*findNetworkChannelByOwner(std::list<NetworkChannel*> *channelList, NetworkClient *networkClient);
	void						*findNetworkServerByLocalNode(std::list<NetworkServer*> *serverList, LocalNode *localNode);
	NetworkServer 				*findNetworkServerByName(std::string& name);
	void 						*findNetworkServerByClients(std::list<NetworkServer*> *serverList, std::list<NetworkClient*> *clientList);
	void 						*findLocalServerByNetworkServer(std::list<LocalServer*> *localServerList, std::list<NetworkServer*> *networkServerList);

public:

	IBRCNetworkManager(ConnectionManager *connectionManager);

	void processData();

	static std::list<MessagePackage*> *getInboundMessagePackageList();
	static std::list<MessagePackage*> *getOutboundMessagePackageList();


	std::list<NetworkServer*> *getNetworkServerList();
	std::list<NetworkClient*> *getNetworkClientList();
	std::list<NetworkChannel*> *getNetworkChannelList();

	IBRCNetworkManagerState getState();
};


#endif /* NETWORKMANAGER_HPP_ */
